package convert.converter;

import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.*;
import java.io.*;
import java.util.*;

public class xml_to_yaml {
    public static void main(String[] args) {
        String xmlFilePath = "src/resource/xml/csv_output.xml";
        String yamlFilePath = "src/resource/yaml/output.yaml";

        convertXMLToYAML(xmlFilePath, yamlFilePath);
    }

    public static void convertXMLToYAML(String xmlFilePath, String yamlFilePath) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new File(xmlFilePath));

            DumperOptions options = new DumperOptions();
            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);

            Yaml yaml = new Yaml(options);
            FileWriter writer = new FileWriter(yamlFilePath);
            writer.write(yaml.dump(getNodeAsMap(document.getDocumentElement())));
            writer.close();

            System.out.println("XML to YAML conversion completed successfully.");
        } catch (ParserConfigurationException | SAXException | IOException e) {
            e.printStackTrace();
        }
    }

    private static Object getNodeAsMap(Node node) {
        Map<String, Object> map = new LinkedHashMap<>();
        NamedNodeMap attributes = node.getAttributes();

        if (attributes.getLength() > 0) {
            Map<String, Object> attributeMap = new LinkedHashMap<>();
            for (int i = 0; i < attributes.getLength(); i++) {
                attributeMap.put(attributes.item(i).getNodeName(), attributes.item(i).getNodeValue());
            }
            map.put("_attributes", attributeMap);
        }

        if (node.hasChildNodes()) {
            NodeList nodeList = node.getChildNodes();

            if (nodeList.getLength() == 1 && nodeList.item(0).getNodeType() == Node.TEXT_NODE) {
                return nodeList.item(0).getNodeValue();
            }

            Map<String, Object> childrenMap = new LinkedHashMap<>();
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node childNode = nodeList.item(i);

                if (childNode.getNodeType() == Node.ELEMENT_NODE) {
                    if (childrenMap.containsKey(childNode.getNodeName())) {
                        Object childValue = childrenMap.get(childNode.getNodeName());
                        if (childValue instanceof List) {
                            ((List<Object>) childValue).add(getNodeAsMap(childNode));
                        } else {
                            List<Object> childList = new ArrayList<>();
                            childList.add(childValue);
                            childList.add(getNodeAsMap(childNode));
                            childrenMap.put(childNode.getNodeName(), childList);
                        }
                    } else {
                        childrenMap.put(childNode.getNodeName(), getNodeAsMap(childNode));
                    }
                }
            }

            if (attributes.getLength() == 0 && childrenMap.size() == 1) {
                return childrenMap.values().iterator().next();
            }

            if (attributes.getLength() == 0) {
                return childrenMap;
            }

            map.putAll(childrenMap);
        }

        return map;
    }
}
